# -*- coding: UTF-8 -*-
# @Create   : 2021/10/8 15:13
# @Author   : yh
# @Remark   :
import logging
from typing import List

from mxsoftpy import DB
from mxsoftpy.exception import DBError, ParamsError
from bsmiddle import ModifyIp
from index import _
from mxsoftpy.TreeDB import symbol_map
from mxsoftpy.db_def.def_type import type_map
from db.common.NetworkManage.IpAM import modify


class IPDB(DB):

    def subnet_items(self, company: str, network: str, subnet: str):
        """
        返回子网信息
        """
        try:
            self.tree.open('Co', '%s\\Net\\%s\\SubNet\\%s' % (company, network, subnet), file='ipctrl')
        except DBError as e:
            logging.error('查询子网时，打开数据库子键失败，公司code：%s，网络code：%s，子网code：%s，错误详情：%s' % (company, network, subnet, str(e)))
            raise ParamsError(_('查询子网信息失败'))

        return self.tree.items()

    def check_ip(self, ip):
        """
        新增检查IP是否存在-zyl
        :param ip: IP地址
        :return:
        """
        QIS = [{"name": "ip", "nCondition": symbol_map['e'], "vLiData": ip,
                "vLiDataType": type_map['str']}]
        key = []
        self.tree.exec_bs('bs_treedb_query_subkey_by_condition', QIS, '', key, 0, 0)
        if key:
            raise Exception('IP地址已存在')

    #@modify
    def create(self, company: str, network: str, **kwargs) -> str:
        """
        新增ip
        :param company: 公司code
        :param network: 网络code
        :param kwargs: 新增的字段及内容
        :return: 新增的子键code
        """
        try:
            # 新增判断IP子健是否存在  ————zyl
            sub_key = self.tree.open('Co', '%s\\Net\\%s' % (company, network), file='ipctrl').sub_keys()
            if 'IP' not in sub_key:
                self.tree.insert_sub_keys('IP')
            self.tree.open('Co', '%s\\Net\\%s\\IP' % (company, network), file='ipctrl')
        except DBError as e:
            logging.error('新增ip时，打开数据库子键失败，公司code：%s，网络code：%s，错误详情：%s' % (company, network, str(e)))
            raise ParamsError(_('新增ip失败'))
        # 新增检查IP是否存在

        self.check_ip(kwargs['ip'])
        try:
            self.tree.insert_key_items(items=kwargs, key=kwargs['ip'])
        except DBError as e:
            logging.error(
                '新增ip时，插入数据到数据库失败，可能的原因：数据库已存在子键[%s]，插入的数据详情：%s，错误详情：%s' % (kwargs['ip'], str(kwargs), str(e)))
            raise ParamsError(_('新增ip失败'))

        ModifyIp(company, network, kwargs['ip'], 0)  # 通知数据库修改到c++末尾参数表示操作 0：新增IP
        return kwargs['ip']

    #@modify
    def delete(self, **kwargs) -> List[str]:
        """
        删除ip
        """
        try:
            self.tree.open('Co', '%s\\Net\\%s\\IP' % (kwargs['company'], kwargs['network']), file='ipctrl')
        except DBError as e:
            logging.error(
                '删除ip时，打开数据库子键失败，公司code：%s，网络code：%s，错误详情：%s' % (kwargs['company'], kwargs['network'], str(e)))
            raise ParamsError(_('删除ip失败'))

        errors = []
        for i in kwargs['ip'].split(';'):
            try:
                self.tree.delete(i)
            except DBError as e:
                errors.append(i)
                logging.error('删除ip时，删除键：%s失败，可能的原因：键不存在，错误详情：%s' % (i, str(e)))
            ModifyIp(kwargs['company'], kwargs['network'], i, 1)  # 通知数据库修改到c++末尾参数表示操作 1：删除IP
        return errors

    #@modify
    def retrieve(self, ip: str, network: str, company: str) -> dict:
        """
        获取ip详情
        :param ip: 要获取的ip
        :param company: 公司code
        :param network: 网络code
        """
        try:
            self.tree.open('Co', '%s\\Net\\%s\\IP\\%s' % (company, network, ip), file='ipctrl')
        except DBError as e:
            logging.error('获取ip详情时，打开数据库子键失败，公司code：%s，网络code：%s，ip：%s错误详情：%s' % (company, network, ip, str(e)))
            raise ParamsError(_('获取ip详情失败'))

        return self.tree.items()

    #@modify
    def update(self, company, network, ip, **kwargs) -> str:
        """
        更新ip
        :param company: 公司code
        :param network: 网络code
        :param ip: 要更新的ip
        :param kwargs: 更新的字段及内容
        """
        try:
            self.tree.open('Co', '%s\\Net\\%s\\IP\\%s' % (company, network, ip), file='ipctrl')
        except DBError as e:
            logging.error('更新ip时，打开数据库子键失败，公司code：%s，网络code：%s，ip：%s错误详情：%s' % (company, network, ip, str(e)))
            raise ParamsError(_('更新ip失败'))

        self.tree.insert_items(kwargs)
        ModifyIp(company, network, ip, 2)  # 通知数据库修改到c++末尾参数表示操作 2：修改IP
        return ip

    #@modify
    def trust(self, company, network, trusts) -> List[str]:
        """
        添加ip信任
        :param trusts: 要添加信任的ip列表
        :param network: 所属网络code
        :param company: 所属公司code
        """
        errors = []
        for ip in trusts.split(','):
            try:
                self.tree.open('Co', '%s\\Net\\%s\\IP\\%s' % (company, network, ip), file='ipctrl')
            except DBError as e:
                logging.error('添加ip信任时，打开数据库子键失败，公司code：%s，网络code：%s，ip：%s错误详情：%s' % (company, network, ip, str(e)))
                errors.append(ip)
                continue

            self.tree.insert_item('isOld', 1)
            ModifyIp(company, network, ip, 2)  # 通知数据库修改到c++末尾参数表示操作 2：修改IP

        return errors
